package com.example.rwq_test.niuke.stack;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Objects;
import java.util.Stack;

/**
 * 四则运算,需要支持带括号的
 *
 * @author renweiqiang
 * @version 1.0.0
 * @createTime 2023/12/21
 */
public class FourOperationFunction {
    private static final Stack<Integer> nums = new Stack<>();
    private static final Stack<Character> ops = new Stack<>();

    public static void main(String[] args) {
        String str = "-11 + (-1-2*3+ (3*7-1))";
        fun(str);
        System.out.println(nums.pop());
    }

    private static void fun(String str) {
        str = str.replace(" ", "");
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (c == '(') {
                ops.push(c);
            } else if (c == ')') {
                doFourFun('(');
            } else if (Character.isDigit(c)) {
                i = doNumFun(str, i);
            } else {
                if (c == '-' && i != 0 && !Character.isDigit(str.charAt(i - 1))) {
                    i = doNumFun(str, ++i);
                    nums.push(-nums.pop());
                } else {
                    ops.push(c);
                }
            }
        }
        doFourFun(null);
    }

    private static void doCalMulOrDiv() {
        Deque<Integer> ints = new ArrayDeque<>();
        Deque<Character> chars = new ArrayDeque<>();
        while (!ops.isEmpty() && (ops.peek() == '*' || ops.peek() == '/')) {
            ints.offer(nums.pop());
            chars.offer(ops.pop());
        }
        int result = nums.pop();
        while (!chars.isEmpty()) {
            result = chars.pollLast() == '*' ? result * ints.pollLast() : result / ints.pollLast();
        }
        nums.push(result);
    }

    private static int doNumFun(String str, int i) {
        Integer result = 0;
        while (i < str.length() && Character.isDigit(str.charAt(i))) {
            result = result * 10 + Character.getNumericValue(str.charAt(i++));
        }
        nums.push(result);
        return --i;
    }

    private static void doFourFun(Character end) {
        Deque<Integer> ints = new ArrayDeque<>();
        Deque<Character> chars = new ArrayDeque<>();
        while (end == null ? !ops.isEmpty() : !Objects.equals(ops.peek(), end)) {
            Character peek = ops.peek();
            if (peek == '*' || peek == '/') {
                doCalMulOrDiv();
            } else {
                ints.offer(nums.pop());
                chars.offer(ops.pop());
            }
        }
        if (end != null) {
            ops.pop();
        }
        Integer result = nums.isEmpty() ? 0 : nums.pop();
        while (!chars.isEmpty()) {
            result = chars.pollLast() == '+' ? result + ints.pollLast() : result - ints.pollLast();
        }
        nums.push(result);
    }
}
